﻿//
// <author>David Nohejl</author>
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WPFTrees.DataStructures;
using WPFTrees.Parser;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Shapes;
using System.Windows.Media;

namespace WPFTrees.Layouts
{
    /// <summary>
    /// Default tree layout.
    /// </summary>
    public class DefaultLayout : LayoutBase
    {
        /// <summary>
        /// Vytvori novou instanci defaultniho layoutu.
        /// </summary>
        public DefaultLayout()
        {
            _branchDrawer = new StraightLineBranchDrawer(Brushes.Black);
        }
        double levelHeight = 50.0;

        /// <inheritdoc />
        public override void ExecuteLayout(Canvas canvas, NTree<NewickNode> tree)
        {
            Point rootPosReal = new Point(canvas.RenderSize.Width / 2.0, 0);
            Size size = canvas.RenderSize;
            TraverseTree(tree.GetRoot(), rootPosReal, size.Width, 1.0);
        }

        /// <summary>
        /// Traverse tree and recompute canvas coordinates.
        /// </summary>
        /// <param name="root"></param>
        /// <param name="rootPos"></param>        
        /// <param name="width"></param>
        /// <param name="scaleRatio"></param>
        void TraverseTree(NTreeNode<NewickNode> root, Point rootPos, 
            double width, double scaleRatio)
        {
            // position root
            FrameworkElement element = root.Value().VisualElement;

            Canvas.SetLeft(element, rootPos.X);
            Canvas.SetTop(element, rootPos.Y);
            // compute positions for children and call recursively
            if (root.CountImmediateChildren == 0)
            {
                // leaf
                Canvas nodeCanvas = root.Value().VisualElement as Canvas;
                Label label = nodeCanvas.Children[1] as Label;
                label.Visibility = DefaultSettings.Default.ShowLabels 
                    ? System.Windows.Visibility.Visible 
                    : System.Windows.Visibility.Hidden;
                return;
            }
            double step = width / (double)root.CountImmediateChildren/* * scaleRatio*/;
            // compute rect for children
            Point childPos = new Point(rootPos.X - width / 2 + step / 2.0, 
                rootPos.Y + levelHeight * scaleRatio);

            foreach (NTreeNode<NewickNode> item in root.Children)
            {
                if (item != null)
                {
                    NewickNode node = item.Value();
                    Line line = node.BranchToParentElement as Line;
                    FrameworkElement visualElement = node.VisualElement; 
                    if (root.Value().IsCollapsed)
                    {
                        line.Visibility = System.Windows.Visibility.Collapsed;
                        visualElement.Visibility = Visibility.Collapsed;
                    }
                    else
                    {
                        line.Visibility = Visibility.Visible;
                        visualElement.Visibility = Visibility.Visible;
                    }
                    line.X1 = rootPos.X;
                    /*+ + node.VisualElement.ActualHeight*/
                    ;
                    line.Y1 = rootPos.Y + element.ActualHeight / 2;
                    DefaultSettings settings = DefaultSettings.Default;
                    double innerNodeOffset = settings.DrawInnerNodes
                                            ? settings.InnerNodeHeight / 2
                                            : 0;
                    double offset = (node.IsLeaf
                                    ? settings.LeafNodeHeight / 2
                                    : innerNodeOffset );
                    line.X2 = childPos.X + offset;
                    line.Y2 = childPos.Y + node.VisualElement.ActualHeight / 2;

                    TraverseTree(item, childPos, step, scaleRatio);
                    childPos.X += step;
                }
            }
        }

    }
}
